//流程服务
module.exports = function (app, models, $, db, nm) {
    return {
        /**
         * 发起流程
         * userId 操作人 必填
         * flowId 流程Id 必填
         * title 任务名称 非必填 不填使用流程名称
         * data 操作数据 必填
         * form 操作项目 非必填
         * toUsers 指定接收人 非必填 userId1,userId2
         * expand1 扩展字段1 非必填
         * expand2 扩展字段2 非必填
         * des 描述 非必填
         * unitId 归属单位 非必填 默认hw
         * **/
        async add(body,headers){
            let flow = await models.f_flow.findSync({id: body.flowId})
            let unitId = body.unitId || 'hw'
            if(!flow.id){
                return { errorMsg:'流程不存在' }
            }
            ///创建流程任务
            let task = {
                f_flowId:flow.id,
                userId:body.userId,
                svg:flow.svg,
                title:body.title || flow.name,
                unitId,
                expand1:body.expand1,
                expand2:body.expand2,
                des:body.des
            }
            let node = await models.f_node.findSync({ id: flow.f_nodeId })
            let action = await models.f_line.findSync({ fromNodeId: node.id })
            let users = action.users ? JSON.parse(action.users) : [],toUsers = []
            for(let i = 0; i < users.length; i ++) {
                // users[i].unitId = users[i].unitId || 'hw'
                // if(unitId == users[i].unitId || (users[i].unitId + '_').indexOf(unitId) == 0){
                //     toUsers.push(users[i].value)
                // }
                toUsers.push(users[i].value)
            }
            if(body.toUsers) toUsers = body.toUsers.split(',')
            let currentNode = await models.f_node.findSync({ id: action.toNodeId })
            if(action.checkUnit){//自动匹配单位
                let users = await models.user.listSync({id:{ $in:toUsers }})
                toUsers = []
                // for(let i = 0; i < users.length; i ++) if(new RegExp('^' + users[i].unitId).test(task.unitId)) toUsers.push(users[i].id)
                for(let i = 0; i < users.length; i ++) if(users[i].unitId == task.unitId) toUsers.push(users[i].id)
            }
            task.toUsers = toUsers.join(',')
            task.f_nodeId = currentNode.id
            task = await models.f_task.insertSync(task)
            if(task.errorMsg){
                return task
            }
            task.svg = null
            let form = body.form || node.form
            form = typeof form == 'object' ? JSON.stringify(form) : form
            ///记录节点信息
            let prevDetail = await models.f_taskDetail.insertSync({
                form,
                data:typeof body.data == 'object' ? JSON.stringify(body.data) : body.data,
                name:node.name,
                status:2,
                f_nodeId:node.id,
                f_taskId:task.id,
                f_flowId:node.f_flowId,
                userId:body.userId,
                toNodeId:action.toNodeId,
                toUsers:toUsers.join(','),
                unitId
            })
            if(prevDetail.errorMsg){
                return prevDetail
            }
            try{
                prevDetail.data = JSON.parse(prevDetail.data)
            }catch(e){
                console.log('发起流程出错',prevDetail.data)
                prevDetail.data = null
            }
            let notify_url = body.notify_url || flow.notify_url
            if(flow.notify_url){
                // let nret = await $.node.fetch({
                //     url:/^http/.test(notify_url) ? notify_url : (Config.hosting + (notify_url[0] == '/' ? notify_url : ('/' + notify_url))),
                //     headers,
                //     data:{
                //         task,
                //         currentNode,
                //         prevDetail
                //     }
                // })
                // if(nret.task){
                //     await models.f_task.updateSync({id:task.id},nret.task);
                // }
            }
            return {
                task,
                currentNode,
                prevDetail
            }
        },
        /**
         * 获取待办任务统计
         * **/
        async count(userId){
            let tables = await db._evalSync(`
            select count(tf.id) as count,max(tf.id) as id,tf.ftype
            from (select t.id,f.type as ftype from f_task as t 
                left join f_flow as f on t.f_flowId = f.id
                where t.toUsers like '%${userId}%' and t.status = 1 order by t.createTime desc) as tf
                group by tf.ftype;
            select id,title,createTimeString from f_task where id in 
                (select max(tf.id) as id
                from (select t.id,f.type as ftype,t.title from f_task as t 
                    left join f_flow as f on t.f_flowId = f.id
                    where t.toUsers like '%${userId}%' and t.status = 1 order by t.id desc) as tf
                    group by tf.ftype);`)
            let taskCount = {},ids = {}
            for(let i = 0; i < tables[0].length; i ++) {
                taskCount[tables[0][i].ftype] = tables[0][i]
                ids[tables[0][i].id] = tables[0][i]
            }
            for(i = 0; i < tables[1].length; i ++){
                ids[tables[1][i].id].title = tables[1][i].title
                ids[tables[1][i].id].createTimeString = tables[1][i].createTimeString
            }
            return taskCount
        },
        /**
         * 操作流程节点
         * f_taskId 流程ID 必填
         * toNodeId 下一节点ID 非必填
         * userId 操作人 非必填
         * toUsers 下一步操作人 非必填
         * data 操作数据 非必填
         * form 操作表单 非必填
         * **/
        async list(query){
            let userId = query.userId
            let type = query.type || 1
            let pageSize = query.pageSize || 10
            let pageNum = query.pageNum || 1
            let sql = {
                projection:{
                    id:1,
                    title:1,
                    userId:1,
                    toUsers:1,
                    expand1:1,
                    expand2:1,
                    status:1,
                    des:1,
                    createTimeString:1//创建时间
                },
                join:{
                    f_flowId:{
                        type: 'LEFT',
                        name: 'f_flow',
                        key: 'id',
                        projection: {
                            name: 'flowName',//流程名称
                            type:'flowType'
                        },
                        query:{
                            type:query.flowType || 'IS NULL'
                        }
                    },
                    userId:{
                        type: 'LEFT',
                        name: 'user',
                        key: 'id',
                        projection: {
                            name: 'userName',//发起人
                        }
                    },
                    f_nodeId:{
                        type: 'LEFT',
                        name: 'f_node',
                        key: 'id',
                        projection: {
                            name: 'nodeName',//当前节点名称
                            statusCode: 1
                        }
                    }
                }
            }
            if(type == 1){//待办任务
                return await models.f_task.listSync({ toUsers:{ $regex: userId },status:1, pageSize, pageNum }, sql)
                // return await models.f_task.listSync({$or:{toUsers:{ $regex: userId},userId },status:1, pageSize, pageNum }, sql))
            }else if(type == 3){
                return await models.f_task.listSync({ userId, pageSize, pageNum }, sql)
            } else if(type == 2){//已办任务
                sql = `
                from (select userId,f_taskId,f_flowId from f_taskDetail where userId = ${userId} group by userId,f_taskId,f_flowId) as t
                left join f_task as t1 on t.f_taskId = t1.id
                left join f_flow as f on f.id = t1.f_flowId
                `
                let whereSql = `where ${query.flowType ? 'f.type="' + query.flowType + '"' : 'f.type IS NULL'}`
                let ret = await db._evalSync(`
                    select t1.id,t1.des,t1.status,t1.toUsers,t1.userId,t1.title,t1.expand1,t1.expand2,t1.createTime,t1.createTimeString,u.name as userName,n.name as nodeName,f.name as flowName
                    ${sql}
                    left join f_node as n on n.id = t1.f_nodeId
                    left join user as u on u.id = t1.userId 
                    ${whereSql}
                    order by t1.createTime desc
                    LIMIT ${pageSize} OFFSET ${pageSize * (pageNum - 1)};
                    select count(*) as total
                    ${sql}
                    ${whereSql};
                `)
                return {
                    total: ret[1] ? ret[1][0].total : 0,
                    rows: ret[0]
                }
            }
        },
        /**
         * 更新流程
         * f_taskId 流程ID 必填
         * toNodeId 下一节点ID 非必填
         * userId 操作人 非必填
         * toUsers 下一步操作人 非必填
         * data 操作数据 非必填
         * form 操作表单 非必填
         * **/
        async update(body,headers){
            let userId = body.userId
            console.log('操作流程',body)
            if(!body.taskId) return { errorMsg:'传入参数错误' }
            //流程详情
            let task = await models.f_task.findSync({ id:body.taskId }, {
                join:{
                    f_flowId:{
                        type:'LEFT',
                        name:'f_flow',
                        key:'id',
                        projection:{
                            notify_url:1
                        }
                    }
                }
            })
            if(task.errorMsg) {
                console.log('更新流程出错,获取流程详情错误',task)
                return task
                return false
            }
            task.svg = null
            let toNodeId = body.toNodeId,action;
            if(!toNodeId){
                action = await models.f_line.listSync({ fromNodeId:task.f_nodeId })
                if(action.length > 1){
                    console.log('更新流程出错,请指定下一步操作',action)
                    return { errorMsg:'更新流程出错,请指定下一步操作' }
                }else if(action.length == 1){
                    action = action[0]
                    toNodeId = action.toNodeId
                }else{
                    console.log('更新流程出错,当前节点最后无后续节点',action)
                    return { errorMsg:'更新流程出错,当前节点最后无后续节点' }
                }
            }else{
                action = await models.f_line.findSync({ fromNodeId:task.f_nodeId,toNodeId })
                if(action.errorMsg){
                    console.log('更新流程出错,指定后续节点错误',action)
                    return { errorMsg:'更新流程出错,指定后续节点错误' }
                }
            }
            //当前节点
            let node = await models.f_node.findSync({ id:task.f_nodeId })
            if(node.errorMsg) {
                console.log('更新流程出错,获取当前节点错误',node)
                return node
            }
            let form = body.form
            if(!form){
                form = $.string(node.form).parse({})
                if(form[toNodeId]) form = form[toNodeId]
                // form.toUsers = toUsers
                // form.remark = data.remark
            }
            //下一节点
            let toNode = await models.f_node.findSync({ id:toNodeId })
            if(toNode.errorMsg) {
                console.log('更新流程出错,获取下一节点错误',toNode)
                return toNode
            }
            //保存操作记录
            let data = body.data || {}, toUsers = body.toUsers
            if(!toUsers){
                switch(action.userType){
                    case 'start'://发起人
                        toUsers = task.userId
                        break;
                    case 'prev'://上一处理人
                        let prevDetail = await models.f_taskDetail.listSync({
                            toNodeId: task.f_nodeId,
                            f_taskId: task.id
                        })
                        toUsers = prevDetail[prevDetail.length - 1].userId
                        break;
                    case 'self'://当前处理人
                        toUsers = userId
                        break;
                    case 'select'://选择用户
                        let users = $.string(action.users).parse([])
                        toUsers = []
                        for(let i = 0; i < users.length; i ++) toUsers.push(users[i].value)
                        if(action.checkUnit){//自动匹配单位
                            let _users = await models.user.listSync({id:{ $in:toUsers }})
                            toUsers = []
                            // for(let i = 0; i < _users.length; i ++) if(new RegExp('^' + _users[i].unitId).test(task.unitId)) toUsers.push(_users[i].id)
                            for(let i = 0; i < _users.length; i ++) if(_users[i].unitId == task.unitId) toUsers.push(_users[i].id)
                            toUsers = toUsers.join(',')
                        }
                        break;
                }
            }
            data.toUsers = toUsers
            //保存操作记录
            let taskDetail = await models.f_taskDetail.insertSync({
                form:JSON.stringify(form),
                data:JSON.stringify(data),
                name:`${node.name}[${action.name}]`,
                status: 2,
                userId,
                toNodeId,
                f_nodeId: node.id,
                f_taskId: task.id,
                f_flowId: task.f_flowId,
                remark:data.remark
            })
            if(taskDetail.errorMsg){
                console.log('更新流程出错,保存当前操作记录错误',taskDetail)
                return taskDetail
            }
            //下一节点后续操作
            let toNodeActions = await models.f_line.findSync({ fromNodeId:toNodeId })
            let f_taskUpdateRes = await models.f_task.updateSync({ id:task.id },{
                status: toNodeActions.nodata ? 2 : 1,//后续无操作，流程完结
                toUsers,
                f_nodeId: toNodeId,
                f_taskDetailId: taskDetail.id 
            })
            if(f_taskUpdateRes.errorMsg){
                console.log('更新流程出错,更新流程状态错误',f_taskUpdateRes)
                return taskDetail
            }
            //通知业务系统
            let notify_url = body.notify_url || task.notify_url
            if (notify_url) {
                let nret = await $.node.fetch({
                    url:/^http/.test(notify_url) ? notify_url : (Config.hosting + (notify_url[0] == '/' ? notify_url : ('/' + notify_url))),
                    // url:'https://jlpobuge.cn' + notify_url,
                    headers,
                    data:{
                        task, //流程任务信息
                        currentNode: toNode, //当前节点信息
                        prevDetail: taskDetail //前一处理结果
                    }
                })
                console.log(3,nret)
                if(nret.task) await models.f_task.updateSync({ id:task.id }, nret.task)
            }
            return {
                task, //流程任务信息
                currentNode: toNode, //当前节点信息
                prevDetail: taskDetail //前一处理结果
            }
        }
    }
}